import os
import random
import time
import tkinter as tk
from tkinter import messagebox, simpledialog
from tkinter import ttk

import pandas as pd
from PIL import ImageTk, Image
# from selenium import webdriver
from selenium.webdriver.common.by import By
from ttkthemes import ThemedStyle

from utils import get_data, init_data, browser_init

# 获取当前文件夹路径
current_path = os.path.dirname(os.path.abspath(__file__))
driver_path = os.path.join(current_path, 'drivers', 'chromedriver.exe')
config_path = os.path.join(current_path, 'config', 'settings.ini')
icon_path = os.path.join(current_path, 'resources', 'icons', 'temp_icon.png')

# 配置文件路径
GET_CONFIG_PATH = os.path.join(current_path, 'config/config.xlsx')
videos_page_path = os.path.join(current_path, 'config/作品管理.xlsx')
home_page_path = os.path.join(current_path, 'config/个人主页.xlsx')
setting_page_path = os.path.join(current_path, 'config/设置页.xlsx')

# 图标路径
GET_ICON_PATH = os.path.join(current_path, './临时图标/抓取.png')
MODIFY_ICON_PATH = os.path.join(current_path, './临时图标/修改.png')
CLEAR_ICON_PATH = os.path.join(current_path, './临时图标/清除.png')

MAX_ICON_SIZE = (30, 30)


videos_list = []  # 存放所有作品的键
# config_data_type = {}  # 名称-xpath字典
# config_data_xpath = {}  # 名称-修改方式字典


def resize_image(image_path, max_size):
    img = Image.open(image_path)
    img.thumbnail(max_size, Image.LANCZOS)
    return ImageTk.PhotoImage(img)


def read_all_config(file_path):
    data = pd.read_excel(file_path)
    return data


def read_config(file_path):
    """
    读取Excel配置文件，创建两个字典。
    第一个字典键为第一列值，值为第二列值（NaN替换为空字符串）；
    第二个字典键为第一列值，值为第三列值（NaN替换为空字符串）。

    参数:
    file_path (str): 配置文件的路径。

    返回:
    tuple: 包含两个字典的元组，其中值中的NaN已被替换为空字符串。
    """
    # 使用pandas读取Excel文件
    # global config_data_xpath
    # global config_data_type
    df = pd.read_excel(file_path)

    # 检查是否有至少三列
    if len(df.columns) < 3:
        raise ValueError("配置文件至少需要包含三列数据")

    # 将第二列和第三列中的NaN替换为空字符串
    df[df.columns[1]] = df[df.columns[1]].fillna('')
    df[df.columns[2]] = df[df.columns[2]].fillna('')

    # 创建第一个字典：第一列作为键，第二列作为值（已处理NaN）
    config_data_xpath = df.set_index(df.columns[0])[df.columns[1]].to_dict()

    # 创建第二个字典：第一列作为键，第三列作为值（已处理NaN）
    config_data_type = df.set_index(df.columns[0])[df.columns[2]].to_dict()
    print(config_data_xpath)
    print((config_data_type))

    return config_data_xpath, config_data_type


# def modify_elements_info(driver, gui_data, config_data_xpath, config_data_type):
#     """修改页面的元素"""
#     time.sleep(5)
#     # 遍历当前要修改的元素
#     for name, xpath in config_data_xpath.items():
#         type = config_data_type[name]
#         value = gui_data[name]
#         element = driver.find_element(By.XPATH, xpath)
#
#         if type == 'text' or type == '':
#             # 对于非表单元素，使用JavaScript修改
#             driver.execute_script(f"arguments[0].innerText = '{value}';", element)
#         elif type == 'src':
#             # 修改src属性
#             driver.execute_script("arguments[0].setAttribute('src', arguments[1]);", element, value)
#         elif type == '非直接修改':
#             continue
#         else:
#             print('未定义修改方式，不做处理')


def clear_all_videos(driver):
    """删除当前页面的所有视频元素"""
    time.sleep(5)
    parent = driver.find_element(By.XPATH, '//*[@id="root"]/div//div[@class="all-content-list"]')
    # 找到父元素的所有子元素
    children_elements = parent.find_elements(By.XPATH, "*")
    # 保留第一个和最后一个子元素，删除其他子元素
    for i in range(1, len(children_elements) - 1):
        child_element = children_elements[i]
        driver.execute_script("arguments[0].remove()", child_element)


def change_jiantou_text(driver, n1, n2, n3):
    """构造修改粉丝数，阅读数、收益下面的小标签，带箭头"""
    # 粉丝变化
    # n1 = random.randint(10, 100)
    xpath = '//*[@id="root"]/div/div/div[1]/div[1]/div[1]/div[1]/div/div[3]/p'
    element = driver.find_element(By.XPATH, xpath)
    js_code = f"""
        var pElement = arguments[0];
        pElement.className = 'second-title up';
        pElement.innerHTML = '昨日<span>{n1}</span> <i class="up"></i>';
    """
    driver.execute_script(js_code, element)

    # 阅读变化
    # n = random.randint(10000, 100000)
    xpath = '//*[@id="root"]/div/div/div[1]/div[1]/div[1]/div[2]/div/div[3]/p'
    element = driver.find_element(By.XPATH, xpath)
    js_code = f"""
        var pElement = arguments[0];
        pElement.className = 'second-title up';
        pElement.innerHTML = '昨日<span>{n2:,}</span> <i class="up"></i>';
    """
    driver.execute_script(js_code, element)

    # 收益变化
    # n = round(random.uniform(10.01, 100.01), 2)
    xpath = '//*[@id="root"]/div/div/div[1]/div[1]/div[1]/div[3]/div/div[3]/p'
    element = driver.find_element(By.XPATH, xpath)
    js_code = f"""
        var pElement = arguments[0];
        pElement.className = 'second-title up';
        pElement.innerHTML = '昨日<span>{n3}</span> <i class="up"></i>';
    """
    driver.execute_script(js_code, element)




def add_video(driver, video):
    """新增视频元素"""
    parent = driver.find_element(By.XPATH, '//*[@id="root"]/div//div[@class="all-content-list"]')
    # 找到父元素的所有子元素
    children_elements = parent.find_elements(By.XPATH, "*")
    last_child = children_elements[-1]

    # 创建一个新的div元素
    div = make_div(video)

    # 在最后一个子元素之前插入新的 div
    driver.execute_script("arguments[0].parentNode.insertBefore(document.createRange().createContextualFragment(arguments[1]).children[0], arguments[0]);", last_child, div)


# def modify_eles(driver, gui_data, config_data_xpath, config_data_type):
#     """修改其他元素信息"""
#     time.sleep(5)
#     for name, xpath in config_data_xpath.items():
#         type = config_data_type[name]
#         value = gui_data[name]
#         print(name)
#
#         for x in xpath.split(','):
#             element = driver.find_element(By.XPATH, x)
#             if type == 'text' or type == '':
#                 # 对于非表单元素，使用JavaScript修改
#                 driver.execute_script(f"arguments[0].innerText = '{value}';", element)
#             elif type == 'src':
#                 # 修改src属性
#                 driver.execute_script("arguments[0].setAttribute('src', arguments[1]);", element, value)
#
#             else:
#                 print('未定义修改方式，不做处理')
def modify_eles(driver, gui_data, config_data_xpath, config_data_type):
    """修改其他元素信息"""
    time.sleep(5)
    for name, xpath in config_data_xpath.items():
        type = config_data_type[name]
        value = gui_data[name]

        print('===========================')
        print(name)
        print(value)
        print('===========================')

        for x in xpath.split(','):
            element = driver.find_element(By.XPATH, x)
            if type == 'text' or type == '':
                current_class = element.get_attribute("class")
                # 检查类名中是否包含"empty"
                if "empty" in current_class:
                    # 构造新的class列表，移除"empty"
                    new_class_list = current_class.split()
                    new_class_list = [cls for cls in new_class_list if cls != "empty"]
                    new_class = " ".join(new_class_list)

                    # 更新元素的class属性
                    driver.execute_script(f"arguments[0].className = '{new_class}';", element)

                if name == '用户简介':
                    if isinstance(value, str):
                        value = value.replace('\n', '<br>').replace('\r', '')
                        driver.execute_script(f"arguments[0].innerHTML = '{value}';", element)
                elif name == '总收益':
                    value = f'{value}<span class="income-unit">元</span>'
                    driver.execute_script(f"arguments[0].innerHTML = '{value}';", element)
                elif name == '总阅读':
                    if '万' in value:
                        value = value[:-1]
                        value = f'{value}<span class="unit">万</span>'
                        driver.execute_script(f"arguments[0].innerHTML = '{value}';", element)
                    elif '亿' in value:
                        value = value[:-1]
                        value = f'{value}<span class="unit">亿</span>'
                        driver.execute_script(f"arguments[0].innerHTML = '{value}';", element)
                    else:
                        driver.execute_script(f"arguments[0].innerText = '{value}';", element)
                elif name == '头条号id':
                    value = f'{value}<a style="margin-left: 24px;">复制ID</a>'
                    driver.execute_script(f"arguments[0].innerHTML = '{value}';", element)


                else:
                    # 如果不需要移除"empty"，直接修改内容
                    driver.execute_script(f"arguments[0].innerText = '{value}';", element)
            elif type == 'src':
                # 同样使用f-string
                driver.execute_script(f"arguments[0].setAttribute('src', '{value}');", element)
            else:
                print('未定义修改方式，不做处理')


def make_div(video):
    """创建当前的视频块"""
    tags = ["已发布", "原创", "创作活动"]
    tag01 = tags[0]
    tag02 = tags[1]
    tag03 = tags[2]

    div = f"""<div>
    <div class="genre-item genre-item-in-all-tab">
        <div class="xigua-m-article-card-item">
            <div class="m-content">
                <div class="article-card-wrap">
                    <a class="image link" href="https://www.ixigua.com/i7364294059516658230/" target="_blank" rel="noopener referrer">
                        <img class="hover-img normal" src="{video['封面']}">
                        <div class="m-video-time">
                            <svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 8 8" class="icon-play">
                                <g fill="none" fill-rule="evenodd">
                                    <path d="M0 0h8v8H0z"></path>
                                    <path fill="currentColor" stroke="currentColor" stroke-linejoin="round" d="M1 1l5 3-5 3z"></path>
                                </g>
                            </svg><span class="time">{video['时长']}</span>
                        </div>
                    </a>
                    <div class="article-card-bone">
                        <div class="title-wrap"><a class="article-title" href="https://www.ixigua.com/i7364294059516658230/" target="_blank" rel="noopener referrer">{video['标题']}
                        </div>
                        <div class="xigua-m-label-icons">
                            <div class="m-label">
                                <div class="byte-tag byte-tag-checked byte-tag-size-default byte-tag-simple byte-tag-grey">{tag01}</div>
                                <div class="byte-tag byte-tag-checked byte-tag-size-default byte-tag-simple byte-tag-blue">{tag02}</div>
                                <div class="byte-tag byte-tag-checked byte-tag-size-default byte-tag-simple byte-tag-green">{tag03}</div>
                              
                            </div>
                            <div class="m-icons"></div>
                        </div>
                        <ul class="count video-manage">
                          <li class="count-item">展现 {video['展现']}</li>
                            <li class="count-item">播放 {video['播放']}</li>
                            <li class="count-item like">点赞 {video['点赞']}</li>
                            <li class="count-item link comment">评论 {video['评论']}</li>
                        </ul>
                        <div class="create-time"><span>{video['时间']}</span>
                        </div>
                    </div>
                </div>
            </div>
            <div class="xigua-article-action-list">
                <div class="action-content">
                    <div class="item">
                        <div class="item-inner"><span>查看数据</span>
                        </div>
                    </div>
                    <div class="item">
                        <div class="item-inner"><span>查看评论</span>
                        </div>
                    </div>
                    <div class="item">
                        <div class="item-inner"><span>修改</span>
                        </div>
                    </div>
                    <div class="item">
                        <div class="item-inner" tabindex="0"><span>更多</span>
                        </div>
                    </div>
                </div>
            </div>
            <div class="xigua-video-bottom-info"></div>
        </div>
    </div>
</div>"""
    return div


class WebScraperGUI:
    def __init__(self, master):
        self.master = master
        self.gui_data = {}
        style = ThemedStyle(master)
        style.set_theme("equilux")  # 更改为你喜欢的主题

        screen_width = master.winfo_screenwidth()
        screen_height = master.winfo_screenheight()
        window_width = screen_width // 4
        window_height = screen_height
        position_right = screen_width - window_width
        position_top = 0

        master.geometry(f"{window_width}x{window_height}+{position_right}+{position_top}")

        self.master.option_add("*Foreground", "#000000")
        self.master.option_add("*Font", ("Comic Sans MS", 14))
        self.master.configure(bg="#FDEBD0")

        style.configure("Treeview",
                        foreground="#000000",
                        fieldbackground="#F0EAD6",
                        rowheight=25)
        style.map("Treeview",
                  foreground=[("selected", "#FFFFFF")],
                  background=[("selected", "#A6A6A6")])

        # 添加错误行的样式配置
        style.configure("Error.Treeview", foreground="red")
        self.tree = ttk.Treeview(master, columns=("Element", "Value"), show="headings", style="Treeview")
        self.tree.tag_configure('error', foreground='red')

        self.tree.heading("Element", text="元素名称")
        self.tree.heading("Value", text="值")
        self.tree.tag_configure('evenrow', background='lightblue')
        self.tree.grid(row=2, column=0, columnspan=3, padx=20, pady=20, sticky="nsew")

        self.url_entry = tk.Entry(master, width=50)
        self.url_entry.grid(row=0, column=0, columnspan=3, padx=20, pady=20)

        # 加载图标并设置按钮
        self.get_img = resize_image(GET_ICON_PATH, MAX_ICON_SIZE)
        self.modify_img = resize_image(MODIFY_ICON_PATH, MAX_ICON_SIZE)
        self.clear_img = resize_image(CLEAR_ICON_PATH, MAX_ICON_SIZE)

        self.get_button = tk.Button(master, image=self.get_img, command=self.get_info, bg="#FFD700", fg="black",
                                    compound="left", relief="flat")
        self.get_button.image = self.get_img
        self.get_button.grid(row=1, column=0, padx=20, pady=10)

        self.modify_button = tk.Button(master, image=self.modify_img, command=self.modify_homepage, bg="#FFD700",
                                       fg="black",
                                       compound="left", relief="flat")
        self.modify_button.image = self.modify_img
        self.modify_button.grid(row=1, column=1, padx=20, pady=10)

        self.clear_button = tk.Button(master, image=self.clear_img, command=self.clear_table, bg="#FFD700", fg="black",
                                      compound="left", relief="flat")
        self.clear_button.image = self.clear_img
        self.clear_button.grid(row=1, column=2, padx=20, pady=10)

        self.master.grid_rowconfigure(2, weight=1)
        self.master.grid_columnconfigure(0, weight=1)
        self.master.grid_columnconfigure(1, weight=1)
        self.master.grid_columnconfigure(2, weight=1)

    def load_element_names(self):
        """启动时加载元素名称列"""
        config = read_all_config(GET_CONFIG_PATH)
        for name in config['元素名称']:
            self.tree.insert("", tk.END, values=(name, ""))

    def get_info(self):
        url = self.url_entry.get()
        if not url:
            messagebox.showwarning("警告", "请输入网址！")
            return
        # 获取数据
        data = get_data(url)
        data = init_data(data)

        for item in self.tree.get_children():
            self.tree.delete(item)
        for name, value in data.items():
            # 为含有错误信息的行设置错误tag
            tag = 'error' if '自定义' in str(value) else ''
            self.tree.insert("", tk.END, values=(name, value), tags=(tag,))

    def modify_homepage(self):
        # messagebox.showinfo("提示", "修改主页内容功能尚未实现")
        print(self.read_gui_data())
        # config_data_type = {}  # 名称-xpath字典
        # config_data_xpath = {}  # 名称-修改方式字典
        config_data_xpath, config_data_type = read_config(videos_page_path)
        # 作品管理页
        url = "https://mp.toutiao.com/profile_v4/manage/content/all"
        driver = browser_init(url)
        driver.refresh()
        modify_eles(driver, self.gui_data, config_data_xpath, config_data_type)
        clear_all_videos(driver)
        for video in videos_list:
            print(video)
            add_video(driver, video)
        # 确保截图目录存在，如果不存在则创建它
        print('准备截图')
        time.sleep(2)
        try:
            screenshot_dir = '截图'
            if not os.path.exists(screenshot_dir):
                os.makedirs(screenshot_dir)
            print(f"尝试保存截图到: ./{screenshot_dir}/{self.gui_data['昵称']}_作品管理页.png")
            driver.save_screenshot(f'./{screenshot_dir}/{self.gui_data["昵称"]}_作品管理页.png')
            print("截图操作已完成")
        except Exception as e:
            print(f"发生异常：{e}")

        # 个人主页
        url = "https://mp.toutiao.com/profile_v4/index"
        # 打开新标签页并导航到特定URL
        driver.execute_script(f"window.open('{url}');")

        all_windows = driver.window_handles
        # 切换到最后一个窗口-新窗口
        driver.switch_to.window(all_windows[-1])
        time.sleep(1)
        # driver = browser_init(url)
        # driver.get(url)
        driver.refresh()
        time.sleep(3)
        config_data_xpath, config_data_type = read_config(home_page_path)
        n1 = self.gui_data['昨日粉丝增加量']
        n2 = self.gui_data['昨日阅读增加量']
        n3 = self.gui_data['昨日收益增加量']
        change_jiantou_text(driver, n1, n2, n3)
        modify_eles(driver, self.gui_data, config_data_xpath, config_data_type)
        # 确保截图目录存在，如果不存在则创建它
        print('准备截图')
        time.sleep(2)
        try:
            screenshot_dir = '截图'
            if not os.path.exists(screenshot_dir):
                os.makedirs(screenshot_dir)
            print(f"尝试保存截图到: ./{screenshot_dir}/{self.gui_data['昵称']}_个人主页.png")
            driver.save_screenshot(f'./{screenshot_dir}/{self.gui_data["昵称"]}_个人主页.png')
            print("截图操作已完成")
        except Exception as e:
            print(f"发生异常：{e}")


        # 设置页
        url = "https://mp.toutiao.com/profile_v4/personal/info?click_from=header"
        # 打开新标签页并导航到特定URL
        driver.execute_script(f"window.open('{url}');")
        # 假设你有两个窗口
        all_windows = driver.window_handles
        # 切换到最后一个窗口-新窗口
        driver.switch_to.window(all_windows[-1])
        time.sleep(1)
        # driver = browser_init(url)
        # driver.get(url)
        driver.refresh()
        time.sleep(3)
        config_data_xpath, config_data_type = read_config(setting_page_path)
        modify_eles(driver, self.gui_data, config_data_xpath, config_data_type)
        # 确保截图目录存在，如果不存在则创建它
        print('准备截图')
        time.sleep(2)
        try:
            screenshot_dir = '截图'
            if not os.path.exists(screenshot_dir):
                os.makedirs(screenshot_dir)
            print(f"尝试保存截图到: ./{screenshot_dir}/{self.gui_data['昵称']}_设置页页.png")
            driver.save_screenshot(f'./{screenshot_dir}/{self.gui_data["昵称"]}_设置页.png')
            print("截图操作已完成")
        except Exception as e:
            print(f"发生异常：{e}")

        # 无关闭需要
        # driver.quit()

    def clear_table(self):
        for item in self.tree.get_children():
            self.tree.delete(item)
        self.load_element_names()

    def on_cell_double_click(self, event):
        """双击单元格允许编辑"""
        item_id = self.tree.identify_row(event.y)
        if item_id:
            col = self.tree.identify_column(event.x)
            if col == "#2":  # 第二列（Value列）
                element_name = self.tree.item(item_id)['values'][0]
                current_value = self.tree.set(item_id, column="Value")
                new_value = simpledialog.askstring("修改值", f"请输入新的值（当前值：{current_value}）:",
                                                   initialvalue=current_value)
                if new_value is not None:
                    self.tree.set(item_id, column="Value", value=new_value)

    def setup_event_bindings(self):
        """设置事件绑定"""
        self.tree.bind("<Double-1>", self.on_cell_double_click)

    def read_gui_data(self):
        """
        从GUI的Treeview控件中读取所有行的数据到字典中，键为元素名称，值为对应的值。
        每个视频信息单独存储在一个字典中，所有字典组成一个列表。
        """
        gui_data = {}  # 初始化一个字典用于存放从界面表格读取的数据
        global videos_list
        videos_list = []
        current_video = {}  # 用于累积当前视频的全部信息

        # 遍历Treeview中的所有项目
        for item in self.tree.get_children():  # get_children() 返回Treeview中所有项的ID列表
            # 获取当前项目的值，假设每行有两个值：元素名称和数据值
            item_values = self.tree.item(item)['values']

            # 检查是否有足够的值（至少两列）
            if len(item_values) >= 2:
                element_name = item_values[0]  # 元素名称
                value = item_values[1]  # 数据值

                # 当遇到新的视频标题时，开始新的字典
                if element_name.startswith('标题'):

                    if current_video:  # 如果当前视频字典非空，先加入列表
                        videos_list.append(current_video)
                    current_video = {}  # 开始新的字典
                for i in ('标题', '封面', '时长', '时间', '展现', '播放', '评论', '点赞'):
                    if element_name.startswith(i):
                        current_video[i] = value

                # 将数据存入gui_data字典，用于保持原始逻辑
                gui_data[element_name] = value

        # 确保最后一个视频的信息也被加入列表
        if current_video:
            videos_list.append(current_video)
        print(videos_list)
        self.gui_data = gui_data
        return self.gui_data

    def run(self):
        self.load_element_names()
        self.setup_event_bindings()
        self.master.mainloop()


if __name__ == "__main__":
    root = tk.Tk()
    app = WebScraperGUI(root)
    app.run()
